﻿using BCCommon;
using BCCommon.Enums;
using BCCommon.PaymentEnums;
using BCData.TMS.MarketingCoupon.MarketingCoupon;
using BCData.TMS.MarketingCoupon.MarketingCouponAddress;
using BCData.TMS.MarketingCoupon.MarketingCouponType;
using BCData.TMS.VehicleTransportBusinessConfig;
using BCDto.Sim.Admin.Admin;
using BCDto.TMS.MarketingCoupon.MarketingCouponAddress;
using BCDto.TMS.MarketingCoupon.MarketingCouponType;
using BCDto.TMS.MarketingCoupon.MarketingCouponType.MarketingCouponTypeRequest;
using BCEntity.Common.EntityNameConst;
using BCEntity.TMS.MarketingCoupon.MarketingCoupon;
using BCEntity.TMS.MarketingCoupon.MarketingCouponAddress;
using BCEntity.TMS.MarketingCoupon.MarketingCouponType;
using BCService.Common.Area;
using BCService.TMS.Agent.AgentAreaRecord;
using BCService.TMS.AgentWallet;
using BCService.Utils;
using System;
using System.Collections.Generic;
using System.Linq;

namespace BCService.TMS.MarketingCoupon.MarketingCouponType
{
    public class MarketingCouponTypeService : IMarketingCouponTypeService
    {
        private readonly IMarketingCouponTypeData marketingCouponTypeData;
        private readonly IDatabaseContext databaseContext;
        private readonly IRedisService redisService;
        private readonly IMarketingCouponData marketingCouponData;
        private readonly IAgentAreaRecordService agentAreaRecordService;
        private readonly IZoneService zoneService;
        private readonly IMarketingCouponAddressData marketingCouponAddressData;
        private readonly IVehicleTransportBusinessConfigData vehicleTransportBusinessConfigData;
        private readonly IAgentWalletService agentWalletService;
        private readonly string keyType = string.Format("{0}", EntityNameConst.MarketingCouponTypeEntity);
        private readonly string key = string.Format("{0}", EntityNameConst.MarketingCouponEntity);
        public MarketingCouponTypeService(IDatabaseContext databaseContext,
            IMarketingCouponTypeData marketingCouponTypeData,
            IRedisService redisService,
            IMarketingCouponData marketingCouponData,
            IAgentAreaRecordService agentAreaRecordService,
            IZoneService zoneService,
            IMarketingCouponAddressData marketingCouponAddressData,
            IVehicleTransportBusinessConfigData vehicleTransportBusinessConfigData,
            IAgentWalletService agentWalletService)
        {
            this.databaseContext = databaseContext;
            this.marketingCouponTypeData = marketingCouponTypeData;
            this.redisService = redisService;
            this.marketingCouponData = marketingCouponData;
            this.agentAreaRecordService = agentAreaRecordService;
            this.zoneService = zoneService;
            this.marketingCouponAddressData = marketingCouponAddressData;
            this.vehicleTransportBusinessConfigData = vehicleTransportBusinessConfigData;
            this.agentWalletService = agentWalletService;
        }

        public MarketingCouponTypeDto AgentCreate(MarketingCouponTypeRequestDto requestDto, AdminDto admin)
        {
            if (admin.AgentRecord == null)
            {
                throw new ArgumentException(" 用户验证失败,错误操作 ");
            }
            string transportBusiness = null;
            if (!requestDto.IsCommonBusiness)
            {
                if (!requestDto.VehicleTransportBusinessConfigId.HasValue)
                {
                    throw new ArgumentException(" 请选择适用业务,请检查数据 ");
                }
                var vehicleTransportBusinessConfigEntity = vehicleTransportBusinessConfigData.GetEntity(requestDto.VehicleTransportBusinessConfigId.Value.ToInt32()).Result;
                if (vehicleTransportBusinessConfigEntity == null)
                {
                    throw new ArgumentException(" 当前代理商不存在此业务,不可选择 ");
                }
                if (!vehicleTransportBusinessConfigEntity.Enabled)
                {
                    throw new ArgumentException(" 当前代理商此业务已被禁用,不可选择 ");
                }
                transportBusiness = vehicleTransportBusinessConfigEntity.TransportBusiness;
            }
            long agentRecordId = admin.AgentRecord.AgentRecordId;
            var entity = new MarketingCouponTypeEntity
            {
                CouponType = requestDto.CouponType,
                CouponName = requestDto.CouponType,
                CouponSummark = requestDto.CouponSummark,
                CouponAmount = requestDto.CouponAmount,
                CouponCount = requestDto.CouponCount,
                RemainCount = requestDto.CouponCount,
                ReceivedCount = 0,
                UsingCount = 0,
                InvalidCount = 0,
                Enabled = true,
                AgentRecordId = agentRecordId,
                IsCommon = false,
                StartDate = requestDto.StartDate,
                EndDate = requestDto.EndDate,
                CreateTime = DateTime.Now,
                CreateAdminId = admin.AdminId,
                CreateAdminName = admin.FullName,
                UpdateTime = DateTime.Now,
                EditAdminId = admin.AdminId,
                EditAdminName = admin.FullName,
                IsCommonBusiness = requestDto.IsCommonBusiness,
                VehicleTransportBusinessConfigId = requestDto.VehicleTransportBusinessConfigId,
                TransportBusiness = transportBusiness,
            };
            var amount = requestDto.CouponCount * requestDto.CouponAmount;
            string orderNo = Guid.NewGuid().ToString();
            this.databaseContext.BeginTransaction();
            agentWalletService.Pay(admin, amount, "优惠券发放", FlowType.MarketingCoupon, PaymentChannelType.Balance,
               FlowDirectionType.Outlay, orderNo);
            var result = this.marketingCouponTypeData.InsertAsync(entity).GetAwaiter().GetResult();
            var marketingCoupons = new List<MarketingCouponEntity>();

            for (int i = 0; i < requestDto.CouponCount; i++)
            {
                var marketingCoupon = new MarketingCouponEntity
                {
                    MarketingCouponTypeId = result.MarketingCouponTypeId,
                    CouponType = result.CouponType,
                    CouponName = result.CouponType,
                    CouponSummark = requestDto.CouponSummark,
                    CouponCount = requestDto.CouponCount,
                    StartDate = result.StartDate,
                    EndDate = result.EndDate,
                    CouponAmount = result.CouponAmount,
                    IsCommon = result.IsCommon,
                    CouponNumber = i + 1,
                    Enabled = true,
                    AgentRecordId = agentRecordId,
                    CreateTime = DateTime.Now,
                    CreateAdminId = admin.AdminId,
                    CreateAdminName = admin.FullName,
                    IsReceive = false,
                    IsUse = false,
                    IsCommonBusiness = requestDto.IsCommonBusiness,
                    VehicleTransportBusinessConfigId = requestDto.VehicleTransportBusinessConfigId,
                    TransportBusiness = transportBusiness,
                };
                marketingCoupons.Add(marketingCoupon);
            }
            var marketingCouponResult = this.marketingCouponData.InsertAllAsync(marketingCoupons).GetAwaiter().GetResult();
            if (marketingCouponResult != marketingCoupons.Count)
            {
                throw new ArgumentException(" 添加优惠券失败 ");
            }
            this.databaseContext.Commit();
            this.redisService.DeleteMultipleKey(keyType, false);
            this.redisService.DeleteMultipleKey(key, false);
            return result.As<MarketingCouponTypeDto>();
        }

        public bool Disabled(long marketingCouponTypeId, AdminDto admin)
        {
            var entity = this.marketingCouponTypeData.GetSingle(marketingCouponTypeId).GetAwaiter().GetResult();
            if (entity == null)
            {
                throw new ArgumentException(" 获取优惠券类型失败 ");
            }
            entity.Enabled = false;
            this.databaseContext.BeginTransaction();
            var result = this.marketingCouponTypeData.UpdateAsync(entity).GetAwaiter().GetResult();
            if (result != null)
            {
                marketingCouponData.UpdateEnabledByTypeId(marketingCouponTypeId, false).GetAwaiter().GetResult();
            }
            this.databaseContext.Commit();
            this.redisService.DeleteMultipleKey(keyType, false);
            this.redisService.DeleteMultipleKey(key, false);
            return result != null;
        }

        public bool Enabled(long marketingCouponTypeId, AdminDto admin)
        {
            var entity = this.marketingCouponTypeData.GetSingle(marketingCouponTypeId).GetAwaiter().GetResult();
            if (entity == null)
            {
                throw new ArgumentException(" 获取优惠券类型失败 ");
            }
            if (!(entity.EndDate >= DateTime.Now.Date))
            {
                throw new ArgumentException(" 该优惠券已过期,不可启用 ");
            }
            entity.Enabled = true;
            this.databaseContext.BeginTransaction();
            var result = this.marketingCouponTypeData.UpdateAsync(entity).GetAwaiter().GetResult();
            if (result != null)
            {
                marketingCouponData.UpdateEnabledByTypeId(marketingCouponTypeId, true).GetAwaiter().GetResult();
            }
            this.databaseContext.Commit();
            this.redisService.DeleteMultipleKey(keyType, false);
            this.redisService.DeleteMultipleKey(key, false);
            return result != null;
        }

        public IEnumerable<MarketingCouponTypeViewDto> GetList(AdminDto admin, bool? isEnabled, bool? isValid, decimal? couponMinAmount, decimal? couponMaxAmount)
        {
            string cacheKey = this.redisService.GetKey(keyType,admin.AgentRecord.AgentRecordId, isEnabled, isValid, couponMinAmount, couponMaxAmount);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var entity = this.marketingCouponTypeData.GetList(admin.AgentRecord.AgentRecordId, isEnabled, isValid, couponMinAmount, couponMaxAmount).Result.As<IEnumerable<MarketingCouponTypeViewDto>>();
                foreach (var item in entity)
                {
                    item.AllAddress = marketingCouponAddressData.GetAddressStrByTypeId(item.MarketingCouponTypeId).Result;
                    item.StartDate = Convert.ToDateTime(item.StartDate.ToString("D").ToString());
                    item.EndDate = Convert.ToDateTime(item.EndDate.AddDays(1).ToString("D").ToString()).AddSeconds(-1);
                }
                return entity;
            }, TimeSpan.FromDays(1));
            return result;
        }

        public MarketingCouponTypeViewDto GetSingle(long marketingCouponTypeId)
        {
            string cacheKey = this.redisService.GetKey(keyType, marketingCouponTypeId);
            var resultRedis = this.redisService.TryGet(cacheKey, () =>
            {
                var result = this.marketingCouponTypeData.GetSingle(marketingCouponTypeId).GetAwaiter().GetResult().As<MarketingCouponTypeViewDto>();
                if (result == null)
                {
                    throw new ArgumentException(" 获取优惠券类型失败 ");
                }
                result.MarketingCouponAddresses = marketingCouponAddressData.GetListViewAsync(result.MarketingCouponTypeId).Result.As<IEnumerable<MarketingCouponAddressViewDto>>();
                return result;
            }, TimeSpan.FromDays(1));

            return resultRedis;
        }

        public bool SetAddress(long marketingCouponTypeId, MarketingCouponAddressRequestDto requestDto, AdminDto admin)
        {
            var typeEntity = this.marketingCouponTypeData.GetSingle(marketingCouponTypeId).GetAwaiter().GetResult();
            if (typeEntity == null)
            {
                throw new ArgumentException(" 获取优惠券类型失败 ");
            }
            if (admin.AgentRecord == null)
            {
                throw new ArgumentException(" 用户验证失败,错误操作 ");
            }
            if (!requestDto.CountyList.Any())
            {
                throw new ArgumentException(" 请选择需要设置地区的行政地区 ");
            }
            foreach (var itemCountyCode in requestDto.CountyList)
            {
                var zoneEntity = zoneService.GetFromZoneEntity(itemCountyCode);
                if (zoneEntity == null || zoneEntity.provinceEntity == null || zoneEntity.cityEntity == null || zoneEntity.countyEntity == null)
                {
                    throw new ArgumentException("此区域信息不正确!");
                }
                var agentAreaRecordEntity = agentAreaRecordService.GetLastLevelByCode(zoneEntity.countyEntity.CountyCode);
                if (agentAreaRecordEntity == null)
                {
                    throw new ArgumentException(" 当前地区未开通,错误数据 ");
                }
                if (agentAreaRecordEntity.AgentRecordId != admin.AgentRecord.AgentRecordId)
                {
                    throw new ArgumentException(" 当前选择的地区中存在 您未管辖的地区 (" + zoneEntity.countyEntity.CountyName + ") ,请重新选择 ");
                }
            }
            this.databaseContext.BeginTransaction();

            this.marketingCouponAddressData.DeleteByTypeId(marketingCouponTypeId).GetAwaiter().GetResult();
            var addressList = new List<MarketingCouponAddressEntity>();
            foreach (var item in requestDto.CountyList)
            {
                var zoneEntity = zoneService.GetFromZoneEntity(item);
                if (zoneEntity == null || zoneEntity.provinceEntity == null || zoneEntity.cityEntity == null || zoneEntity.countyEntity == null)
                {
                    throw new ArgumentException("此区域信息不正确!");
                }
                var address = new MarketingCouponAddressEntity()
                {
                    MarketingCouponTypeId = typeEntity.MarketingCouponTypeId,
                    CouponType = typeEntity.CouponType,
                    CouponName = typeEntity.CouponName,
                    CouponSummark = typeEntity.CouponSummark,
                    StartDate = typeEntity.StartDate,
                    EndDate = typeEntity.EndDate,
                    CouponAmount = typeEntity.CouponAmount,
                    CouponCount = typeEntity.CouponCount,
                    AgentRecordId = typeEntity.AgentRecordId,
                    IsCommon = typeEntity.IsCommon,
                    ProvinceCode = zoneEntity.provinceEntity.ProvinceCode,
                    CityCode = zoneEntity.cityEntity.CityCode,
                    CountyCode = zoneEntity.countyEntity.CountyCode,
                    CreateTime = DateTime.Now,
                    CreateAdminId = admin.AdminId,
                    CreateAdminName = admin.FullName,
                };
                addressList.Add(address);
            }
            this.marketingCouponAddressData.InsertAllAsync(addressList).GetAwaiter().GetResult();
            this.databaseContext.Commit();
            return true;
        }
    }
}
